package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrPool;
import com.tbit.main.constant.*;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2021-08-23 10:25
 */
@Service("workOrderQuartzService")
public class WorkOrderQuartzServiceImpl implements WorkOrderQuartzService {

    @Autowired
    private WorkOrderConfigService workOrderConfigService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private WorkOrderFinishingService workOrderFinishingService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MachineManagerService machineManagerService;
    @Autowired
    private MachineOccupyService machineOccupyService;
    @Autowired
    private DataService dataService;

    public static void main(String[] args) {
        String input = "Hello 😀, how are you? 🌞";
        String output = removeEmojis(input);
        System.out.println(output);
    }

    public static String removeEmojis(String input) {
        return input.replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}\\x{1F680}-\\x{1F6FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}]", "");
    }

    @Override
    //@Scheduled(cron = "0 1/5 * * * ?")
    public void moveOrder() {
        LogUtil.info("挪车工单定时任务");
        long t1 = System.currentTimeMillis();

        List<WorkOrderConfig> workOrderConfigList = workOrderConfigService.getByType("moveSwitch");

        for (WorkOrderConfig workOrderConfig : workOrderConfigList) {

            /**区域挪车人员*/
            List<Integer> accountUserIds = new LinkedList<>();
            /**分区：挪车人员*/
            Map<Integer, List<Integer>> regionUserIds = new HashMap<>();

            /**区域有定位人员id*/
            List<Integer> accountUserIdsLoc = new LinkedList<>();
            /**分区：有定位人员id*/
            Map<Integer, List<Integer>> regionUserIdsLoc = new HashMap<>();

            /**区域人员*/
            List<AccountUserWorkConfig> accountUserWorkConfigList = dataService.getAccountUserWorkConfigByAccountId(workOrderConfig.getAccountId());
            if (accountUserWorkConfigList != null && accountUserWorkConfigList.size() >= 0) {
                // LogUtil.info("挪车：区域配置运维人员:" + accountUserWorkConfigList.stream().map(AccountUserWorkConfig::getAccountUserId).collect(Collectors.toList()));

                /**挪车总人员*/
                for (AccountUserWorkConfig accountUserWorkConfig : accountUserWorkConfigList) {

                    Boolean timeBoolean = false;

                    if (DateTimeUtil.compareTime(accountUserWorkConfig.getStartTime(), accountUserWorkConfig.getEndTime())) {
                        String startTime = accountUserWorkConfig.getStartTime();
                        String endTime = accountUserWorkConfig.getEndTime();
                        accountUserWorkConfig.setStartTime(endTime);
                        accountUserWorkConfig.setEndTime(startTime);
                        timeBoolean = true;
                    }
                    if (accountUserWorkConfig.getWorkType().equals(WorkOrderConstant.workType_NC)
                    ) {

                        if (timeBoolean && (
                                (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) && DateTimeUtil.compareTimeNow("23:59")) ||
                                        (!DateTimeUtil.compareTimeNow("00:00") && DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())))) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        } else if (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) &&
                                DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        }
                    }
                }

                if (accountUserIds != null && accountUserIds.size() > 0) {

                    /**人员id：最后位置*/
                    Map<Integer, AccountUserLastPos> map = dataService.getByUserId(accountUserIds);
                    for (Integer userKey : map.keySet()) {
                        accountUserIdsLoc.add(userKey);
                    }

                    /**分区挪车人员*/
                    List<Integer> regions = dataService.getAccountIdGeore(workOrderConfig.getAccountId());
                    if (regions != null && regions.size() > 0) {
                        for (Integer region : regions) {
                            regionUserIds.put(region, ListUtil.receiveCollectionList(dataService.getByRegionId(region), accountUserIds));
                            regionUserIdsLoc.put(region, ListUtil.receiveCollectionList(dataService.getByRegionId(region), accountUserIdsLoc));
                        }
                    }

                    /**异常车辆*/
                    List<Integer> abnormalType = new LinkedList<>();
                    abnormalType.add(MachineAbnormalConstant.MACHINE_ABNORMAL_CCQY);
                    abnormalType.add(MachineAbnormalConstant.MACHINE_ABNORMAL_ZW);
                    abnormalType.add(MachineAbnormalConstant.MACHINE_ABNORMAL_JTYC);
                    List<MachineStatusAbnormal> machineStatusList = machineManagerService.getAbnormalType(workOrderConfig.getAccountId(), abnormalType);

                    if (machineStatusList != null && machineStatusList.size() > 0) {
                        // LogUtil.info(workOrderConfig.getAccountId() + "：异常车辆：" + "" + machineStatusList.stream().map(MachineStatusAbnormal::getMachineId).collect(Collectors.toList()));

                        /**运维占用*/
                        List<MachineOccupy> machineOccupyList = machineOccupyService.getByAccountId(workOrderConfig.getAccountId());
                        Map<Integer, Integer> occupyIdMap = new HashMap<>();
                        for (MachineOccupy machineOccupy : machineOccupyList) {
                            occupyIdMap.put(machineOccupy.getMachineId(), machineOccupy.getAccountUserId());
                        }

                        for (MachineStatusAbnormal machineStatusAbnormal : machineStatusList) {
                            // LogUtil.info("挪车判断：" + machineStatusAbnormal.getMachineId() + "::分区" + dataService.getByGeoMachineId(machineStatusAbnormal.getMachineId()));

                            /**是否占用*/
                            if (occupyIdMap.containsKey(machineStatusAbnormal.getMachineId())) {
                                // LogUtil.info("挪车" + machineStatusAbnormal.getMachineId() + "：运维占用：" + occupyIdMap.get(machineStatusAbnormal.getMachineId()));
                                continue;
                            }

                            WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByWorkMachineIdState(WorkOrderConstant.workType_NC, machineStatusAbnormal.getMachineId(), WorkOrderConstant.state_LQ);
                            if (workOrderFinishing != null) {
                                // LogUtil.info(machineStatusAbnormal.getMachineId() + "：已存在挪车工单");
                                continue;
                            }

                            Boolean work = true;
                            /**查询车辆分区*/
                            Integer regionId = dataService.getByGeoMachineId(machineStatusAbnormal.getMachineId());
                            if (regionId != null) {
                                accountUserIdsLoc = regionUserIdsLoc.get(regionId);
                            }

                            // LogUtil.info("挪车定位人员：" + accountUserIdsLoc);
                            MachineStatus machineStatus = dataService.getMachineStatus(machineStatusAbnormal.getMachineId());

                            if (accountUserIdsLoc != null && accountUserIdsLoc.size() > 0) {
                                Map<Double, Integer> minDistance = new TreeMap<>(new Comparator<Double>() {
                                    public int compare(Double obj1, Double obj2) {
                                        return obj1.compareTo(obj2);
                                    }
                                });

                                Point point = new Point();
                                point.setX(machineStatus.getLon());
                                point.setY(machineStatus.getLat());
                                for (Integer userId : accountUserIdsLoc) {
                                    Point pointUser = new Point();
                                    pointUser.setX(map.get(userId).getLon());
                                    pointUser.setY(map.get(userId).getLat());
                                    minDistance.put(GeoUtil.getDistance(point, pointUser), map.get(userId).getAccountUserId());
                                }

                                for (int i = 0; i < minDistance.size(); i++) {
                                    /**判断是否超过工单阈值*/
                                    Integer userId = minDistance.values().stream().findFirst().orElse(i);
                                    Integer countValue = workOrderFinishingService.getUserIdWorkType(userId, WorkOrderConstant.workType_NC);

                                    if (countValue == null || countValue < workOrderConfig.getMoveNumber()) {
                                        workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                                regionId, WorkOrderConstant.workType_NC, WorkOrderConstant.state_LQ, null);
                                        JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_NC, WorkOrderConstant.new_Work);
                                        work = false;
                                        break;
                                    }
                                }
                            }

                            if (work) {
                                if (regionId != null) {
                                    accountUserIds = regionUserIds.get(regionId);
                                }
                                // LogUtil.info("挪车非定位人员：" + accountUserIds);
                                if (accountUserIds != null && accountUserIds.size() > 0) {
                                    for (Integer userId : accountUserIds) {
                                        /**判断是否超过工单阈值*/
                                        Integer countValue = workOrderFinishingService.getUserIdWorkType(userId, WorkOrderConstant.workType_NC);
                                        if (countValue == null || countValue < workOrderConfig.getMoveNumber()) {
                                            workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                                    regionId, WorkOrderConstant.workType_NC, WorkOrderConstant.state_LQ, null);
                                            JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_NC, WorkOrderConstant.new_Work);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        // LogUtil.info(workOrderConfig.getAccountId() + "无异常车辆");
                    }
                }
            }
        }

        long t2 = System.currentTimeMillis();
        LogUtil.info("挪车工单定时任务时间" + (t2 - t1) + "ms");
    }

    @Override
    //@Scheduled(cron = "0 1/4 * * * ?")
    public void lockPowerOrder() {
        LogUtil.info("换电工单定时任务");
        long t1 = System.currentTimeMillis();

        List<WorkOrderConfig> workOrderConfigList = workOrderConfigService.getByType("powerChangeSwitch");

        for (WorkOrderConfig workOrderConfig : workOrderConfigList) {
            // LogUtil.info("换电区域工单打开配置:" + workOrderConfig.getAccountId());

            AccountConfig accountConfig = dataService.getAccountConfig(workOrderConfig.getAccountId());
            /**工单无效判断*/
            List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getByAccountIdAndWorkType(workOrderConfig.getAccountId(), WorkOrderConstant.workType_HD, accountConfig.getSocLimit());
            if (workOrderFinishingList != null && workOrderFinishingList.size() > 0) {
                for (WorkOrderFinishing workOrderFinishing : workOrderFinishingList) {
                    String key = RedisConstant.REDIS_WORK_ORDER_HD + "_" + WorkOrderConstant.workType_HD + workOrderFinishing.getMachineId();
                    String workOrderDate = redisService.get(key);

                    if (workOrderDate != null) {
                        Long changeTime = Long.valueOf(workOrderDate);
                        /**缓存时间大于换电时间*/
                        if ((System.currentTimeMillis() - changeTime) > 600000) {
                            // LogUtil.info("换电无效工单：" + workOrderFinishing.toString());
                            delWorkOrder(workOrderFinishing.getWorkOrderId(), workOrderFinishing);
                            JPush(workOrderFinishing.getGetUserId(), WorkOrderConstant.buildType_V, workOrderFinishing.getWorkType(), WorkOrderConstant.update_Work);
                            redisService.del(key);
                        }
                    } else {
                        redisService.add(key, String.valueOf(System.currentTimeMillis()), 60 * 15);
                        // LogUtil.info("电量正常工单时间:"+redisService.get(key));
                    }
                }
            }


            /**区域换电人员*/
            List<Integer> accountUserIds = new LinkedList<>();
            /**分区：换电人员*/
            Map<Integer, List<Integer>> regionUserIds = new HashMap<>();

            /**区域有定位人员id*/
            List<Integer> accountUserIdsLoc = new LinkedList<>();
            /**分区：有定位人员id*/
            Map<Integer, List<Integer>> regionUserIdsLoc = new HashMap<>();

            /**区域人员*/
            List<AccountUserWorkConfig> accountUserWorkConfigList = dataService.getAccountUserWorkConfigByAccountId(workOrderConfig.getAccountId());
            if (accountUserWorkConfigList != null && accountUserWorkConfigList.size() > 0) {
                // LogUtil.info("换电：区域配置运维人员:" + accountUserWorkConfigList.stream().map(AccountUserWorkConfig::getAccountUserId).collect(Collectors.toList()));

                /**区域换电人员*/
                for (AccountUserWorkConfig accountUserWorkConfig : accountUserWorkConfigList) {
                    Boolean timeBoolean = false;
                    if (DateTimeUtil.compareTime(accountUserWorkConfig.getStartTime(), accountUserWorkConfig.getEndTime())) {
                        String startTime = accountUserWorkConfig.getStartTime();
                        String endTime = accountUserWorkConfig.getEndTime();
                        accountUserWorkConfig.setStartTime(endTime);
                        accountUserWorkConfig.setEndTime(startTime);
                        timeBoolean = true;
                    }
                    if (accountUserWorkConfig.getWorkType().equals(WorkOrderConstant.workType_HD)
                    ) {

                        if (timeBoolean && (
                                (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) && DateTimeUtil.compareTimeNow("23:59")) ||
                                        (!DateTimeUtil.compareTimeNow("00:00") && DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())))) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        } else if (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) &&
                                DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        }
                    }
                }

                if (accountUserIds != null && accountUserIds.size() > 0) {

                    /**人员id：最后位置*/
                    Map<Integer, AccountUserLastPos> map = dataService.getByUserId(accountUserIds);
                    for (Integer userKey : map.keySet()) {
                        accountUserIdsLoc.add(userKey);
                    }

                    /**分区换电人员*/
                    List<Integer> regions = dataService.getAccountIdGeore(workOrderConfig.getAccountId());
                    if (CollUtil.isNotEmpty(regions)) {
                        for (Integer region : regions) {
                            regionUserIds.put(region, ListUtil.receiveCollectionList(dataService.getByRegionId(region), accountUserIds));
                            regionUserIdsLoc.put(region, ListUtil.receiveCollectionList(dataService.getByRegionId(region), accountUserIdsLoc));
                        }
                    }

                    /**缺电车辆*/
                    List<MachineStatus> machineStatusList = machineStatusService.getSocByAccountId(workOrderConfig.getAccountId(), accountConfig.getSocLimit());

                    if (machineStatusList != null && machineStatusList.size() > 0) {
                        // LogUtil.info(workOrderConfig.getAccountId() + "：缺电车辆：" +machineStatusList.stream().map(MachineStatus::getMachineId).collect(Collectors.toList()));

                        /**运维占用*/
                        List<MachineOccupy> machineOccupyList = machineOccupyService.getByAccountId(workOrderConfig.getAccountId());
                        Map<Integer, Integer> occupyIdMap = new HashMap<>();
                        for (MachineOccupy machineOccupy : machineOccupyList) {
                            occupyIdMap.put(machineOccupy.getMachineId(), machineOccupy.getAccountUserId());
                        }

                        for (MachineStatus machineStatus : machineStatusList) {
                            // LogUtil.info("换电判断：" + machineStatus.getMachineId() + "::分区" + dataService.getByGeoMachineId(machineStatus.getMachineId()));

                            /**是否占用*/
                            if (occupyIdMap.containsKey(machineStatus.getMachineId())) {
                                // LogUtil.info("换电" + machineStatus.getMachineId() + "：运维占用：" + occupyIdMap.get(machineStatus.getMachineId()));
                                continue;
                            }

                            WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByWorkMachineIdState(WorkOrderConstant.workType_HD,
                                    machineStatus.getMachineId(), WorkOrderConstant.state_LQ);
                            if (workOrderFinishing != null) {
                                // LogUtil.info(machineStatus.getMachineId() + "：已存在换电工单");
                                continue;
                            }


                            Boolean work = true;

                            /**查询车辆分区*/
                            Integer regionId = dataService.getByGeoMachineId(machineStatus.getMachineId());
                            if (regionId != null) {
                                accountUserIdsLoc = regionUserIdsLoc.get(regionId);
                            }
                            // LogUtil.info("换电定位人员：" + accountUserIdsLoc);

                            if (accountUserIdsLoc != null && accountUserIdsLoc.size() > 0) {
                                Map<Double, Integer> minDistance = new TreeMap<>(new Comparator<Double>() {
                                    public int compare(Double obj1, Double obj2) {
                                        return obj1.compareTo(obj2);
                                    }
                                });

                                Point point = new Point();
                                point.setX(machineStatus.getLon());
                                point.setY(machineStatus.getLat());
                                for (Integer userId : accountUserIdsLoc) {
                                    Point pointUser = new Point();
                                    pointUser.setX(map.get(userId).getLon());
                                    pointUser.setY(map.get(userId).getLat());
                                    minDistance.put(GeoUtil.getDistance(point, pointUser), map.get(userId).getAccountUserId());
                                }

                                for (int i = 0; i < minDistance.size(); i++) {
                                    /**判断是否超过工单阈值*/
                                    Integer userId = minDistance.values().stream().findFirst().orElse(i);
                                    Integer countValue = workOrderFinishingService.getUserIdWorkType(userId, WorkOrderConstant.workType_HD);
                                    if (countValue == null || countValue < workOrderConfig.getPowerChangeNumber()) {
                                        workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                                regionId, WorkOrderConstant.workType_HD, WorkOrderConstant.state_LQ, null);
                                        JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_HD, WorkOrderConstant.new_Work);
                                        work = false;
                                        break;
                                    }
                                }
                            }

                            if (work) {
                                if (regionId != null) {
                                    accountUserIds = regionUserIds.get(regionId);
                                }
                                // LogUtil.info("换电非定位人员：" + accountUserIds);
                                if (accountUserIds != null && accountUserIds.size() > 0) {
                                    for (Integer userId : accountUserIds) {
                                        /**判断是否超过工单阈值*/
                                        Integer countValue = workOrderFinishingService.getUserIdWorkType(userId, WorkOrderConstant.workType_HD);
                                        if (countValue == null || countValue < workOrderConfig.getPowerChangeNumber()) {
                                            workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                                    regionId, WorkOrderConstant.workType_HD, WorkOrderConstant.state_LQ, null);
                                            JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_HD, WorkOrderConstant.new_Work);
                                            break;
                                        }
                                    }
                                }
                            }

                        }
                    } else {
                        // LogUtil.info(workOrderConfig.getAccountId() + "无缺电车辆");
                    }
                }
            }
        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("换电工单定时任务时间" + (t2 - t1) + "ms");
    }

    @Override
    //@Scheduled(cron = "0 1/3 * * * ?")
    public void delWork() {
        LogUtil.info("批量删除redis工单定时任务");
        long t1 = System.currentTimeMillis();

        Set<String> key = redisService.getLikeKeys("*" + RedisConstant.REDIS_WORK_ORDER);

        if (key != null && key.size() > 0) {

            List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getAll();
            List<String> workRedis = new LinkedList<>();
            if (workOrderFinishingList != null && workOrderFinishingList.size() > 0) {
                for (WorkOrderFinishing workOrderFinishing : workOrderFinishingList) {
                    if (workOrderFinishing.getWorkType().equals(WorkOrderConstant.workType_WX)) {
                        workRedis.add(workOrderFinishing.getAccountId() + "_" + workOrderFinishing.getUserCode() + "_" +
                                workOrderFinishing.getWorkType() + "_" + RedisConstant.REDIS_WORK_ORDER);
                    } else {
                        workRedis.add(workOrderFinishing.getAccountId() + "_" + workOrderFinishing.getUserCode() + "_" +
                                workOrderFinishing.getWorkType() + "_" + workOrderFinishing.getState() + "_" + RedisConstant.REDIS_WORK_ORDER);
                    }
                }

                Set<String> delKeys = ListUtil.getSameIntegerSet(key, workRedis);
                redisService.delLikeKeys(delKeys);
                LogUtil.info("批量删除：" + delKeys.toString());
            } else {
                redisService.delLikeKeys(key);
                LogUtil.info("批量删除：" + key.toString());
            }
        }
        long t2 = System.currentTimeMillis();
        LogUtil.info("批量删除redis工单定时任务时间" + (t2 - t1) + "ms");
    }

    @Override
    @Transactional(value = "coreTransactionManager")
    public void workOrder(Integer userId, WorkOrderConfig workOrderConfig, Machine machine,
                          Integer regionId, Integer workType, Integer state, Integer locationType) {
        /**生成工单*/
        WorkOrder workOrder = new WorkOrder();
        /**生成流水号*/
        String serNO = StringUtil.getRideLogOrderNO();
        workOrder.setWorkOrderId(serNO);
        workOrder.setAccountId(workOrderConfig.getAccountId());
        workOrder.setRegionId(regionId);
        workOrder.setMachineType(machine.getMachineType());
        workOrder.setBuildType(WorkOrderConstant.buildType_V);
        workOrder.setPriority(WorkOrderConstant.priority_Second);
        workOrder.setWorkType(workType);
        workOrder.setBuildTime(DateTimeUtil.getNowTime());
        workOrder.setGetTime(DateTimeUtil.getNowTime());
        workOrder.setGetUserId(userId);
        AccountUser accountUser = dataService.getAccountUser(userId);
        if (accountUser != null) {
            workOrder.setGetUserName(accountUser.getName());
        }
        workOrder.setState(state);
        workOrder.setMachineId(machine.getMachineId());
        workOrder.setMachineNO(machine.getMachineNO());
        workOrder.setUserCode(machine.getUserCode());
        // 0: 超区, 1: 站外
        workOrder.setLocationType(locationType);

        workOrderService.insert(workOrder);
        workOrderFinishingService.insert(workOrder);
        LogUtil.info("创建工单: " + workOrder);
    }

    @Override
    public void JPush(Integer userId, Integer buildType, Integer workType, String voice) {

        /**语音推送开关*/
        if (dataService.getByAccountUserId(userId) != null &&
                ((buildType.equals(WorkOrderConstant.buildType_V) && dataService.getByAccountUserId(userId).getAutoMassageSwitch()) ||
                        (buildType.equals(WorkOrderConstant.buildType_H) && dataService.getByAccountUserId(userId).getNotAutoMassageSwitch()))) {

            /**获取极光推送regId*/
            String regId = redisService.get(userId + "_" + RedisConstant.REDIS_WORK_PUSH);

            if (regId != null) {
                String pushKey = userId + "_" + workType + "_" + RedisConstant.REDIS_WORK_PUSH;
                String push = redisService.get(pushKey);

                /**判断极光推送频率*/
                if (push == null) {
                    Integer second = 1;
                    if (buildType.equals(WorkOrderConstant.buildType_V)) {
                        // TODO 下个版本兼容超区、站外挪车语音
                        if (workType.equals(WorkOrderConstant.workType_NC) && !dataService.getByAccountUserId(userId).getMoveHZ().equals(0)) {
                            second = dataService.getByAccountUserId(userId).getMoveHZ() * 60;
                        } else if (workType.equals(WorkOrderConstant.workType_HD) && !dataService.getByAccountUserId(userId).getPowerChangeHZ().equals(0)) {
                            second = dataService.getByAccountUserId(userId).getPowerChangeHZ() * 60;
                        } else if (workType.equals(WorkOrderConstant.workType_DD) && !dataService.getByAccountUserId(userId).getDispatchHZ().equals(0)) {
                            second = dataService.getByAccountUserId(userId).getDispatchHZ() * 60;
                        }
                    } else {
                        if (!dataService.getByAccountUserId(userId).getLabourHZ().equals(0)) {
                            second = dataService.getByAccountUserId(userId).getLabourHZ() * 60;
                        }
                    }

                    redisService.add(pushKey, userId + "", second <= 0 ? 1 : second);
                    LogUtil.info("极光挪车推送：" + pushKey + "_" + regId);
                    JPushService.pushNotice(AppPushConstant.PUSH_TYPE_REGID, regId, "工单", "content", 1, voice);
                }
            }
        }
    }

    @Override
    public void WorkOrder_NC(Machine machine, Integer locationType) {

        LogUtil.info("调度还车:" + machine.getUserCode());
        WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByWorkMachineIdState(WorkOrderConstant.workType_NC, machine.getMachineId(), WorkOrderConstant.state_LQ);

        String alert = WorkOrderConstant.new_Work;

        if (workOrderFinishing != null) { // 重新生成挪车工单
            LogUtil.info("挪车调度重新生成工单：" + workOrderFinishing);
            this.delWorkOrder(workOrderFinishing.getWorkOrderId(), workOrderFinishing);
            alert = Objects.equals(workOrderFinishing.getLocationType(), locationType) ? WorkOrderConstant.update_Work : alert;
        }

        /**区域工单开关配置*/
        WorkOrderConfig workOrderConfig = dataService.getWorkOrderConfig(machine.getAccountId());
        LogUtil.info(String.format("工单配置：%s", workOrderConfig));
        if (workOrderConfig == null) {
            return;
        }

        /**区域挪车人员*/
        Set<Integer> accountUserIds = new HashSet<>();
        /**分区：挪车人员*/
        Map<Integer, Set<Integer>> regionUserIds = new HashMap<>();

        /**区域有定位人员id*/
        Set<Integer> accountUserIdsLoc = new HashSet<>();
        /**分区：有定位人员id*/
        Map<Integer, Set<Integer>> regionUserIdsLoc = new HashMap<>();

        // 运维Id_挪车类型（0:超区，1:站外）
        Set<String> accountUserLocationTypeMap = new HashSet<>();

        /**区域人员*/
        List<AccountUserWorkConfig> accountUserWorkConfigList = dataService.getAccountUserWorkConfigByAccountId(workOrderConfig.getAccountId());

        if (CollUtil.isNotEmpty(accountUserWorkConfigList)) {
            /**挪车总人员*/
            for (AccountUserWorkConfig accountUserWorkConfig : accountUserWorkConfigList) {

                // 没有开启上班打卡，或者开启上班打卡并且有打卡记录的
                if (!workOrderConfig.getClockInOrderSwitch()
                        || Objects.nonNull(dataService.getAccountUserWorkByAccountUserId(accountUserWorkConfig.getAccountUserId()))) {
                    Boolean timeBoolean = false;
                    if (DateTimeUtil.compareTime(accountUserWorkConfig.getStartTime(), accountUserWorkConfig.getEndTime())) {
                        String startTime = accountUserWorkConfig.getStartTime();
                        String endTime = accountUserWorkConfig.getEndTime();
                        accountUserWorkConfig.setStartTime(endTime);
                        accountUserWorkConfig.setEndTime(startTime);
                        timeBoolean = true;
                    }
                    if (accountUserWorkConfig.getWorkType().equals(WorkOrderConstant.workType_NC)) {
                        if (timeBoolean && (
                                (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) && DateTimeUtil.compareTimeNow("23:59")) ||
                                        (!DateTimeUtil.compareTimeNow("00:00") && DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())))) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        } else if (!DateTimeUtil.compareTimeNow(accountUserWorkConfig.getStartTime()) &&
                                DateTimeUtil.compareTimeNow(accountUserWorkConfig.getEndTime())) {
                            accountUserIds.add(accountUserWorkConfig.getAccountUserId());
                        }
                    }

                    String accountUserLocationType = accountUserWorkConfig.getAccountUserId() + StrPool.UNDERLINE + accountUserWorkConfig.getLocationType();
                    // 检查超区的挪车权限
                    if (Objects.equals(accountUserWorkConfig.getLocationType(), MachineLocationTypeConstant.SUPER_ZONE_MOVE)
                            && workOrderConfig.getSuperZoneMoveSwitch()) {
                        accountUserLocationTypeMap.add(accountUserLocationType);
                    }

                    // 检车站外的挪车权限
                    if (Objects.equals(accountUserWorkConfig.getLocationType(), MachineLocationTypeConstant.OUT_SITE_MOVE)
                            && workOrderConfig.getOutSiteMoveSwitch()) {
                        accountUserLocationTypeMap.add(accountUserLocationType);
                    }
                }
            }
        }


        if (CollUtil.isNotEmpty(accountUserIds)) {

            /**人员id：最后位置*/
            Map<Integer, AccountUserLastPos> map = dataService.getByUserId(accountUserIds);
            for (Integer userKey : map.keySet()) {
                accountUserIdsLoc.add(userKey);
            }

            /**分区挪车人员*/
            List<Integer> regions = dataService.getAccountIdGeore(workOrderConfig.getAccountId());
            if (CollUtil.isNotEmpty(regions)) {
                for (Integer region : regions) {
                    List<Integer> regionIds = dataService.getByRegionId(region);
                    regionUserIds.put(region, ListUtil.unionDistinct(regionIds, accountUserIds));  // 获取交集
                    regionUserIdsLoc.put(region, ListUtil.unionDistinct(regionIds, accountUserIdsLoc));  // 获取交集
                }
            }

            MachineStatus machineStatus = dataService.getMachineStatus(machine.getMachineId());

            Boolean work = true;
            /**查询车辆分区*/
            Integer regionId = dataService.getByGeoMachineId(machineStatus.getMachineId());
            if (regionId != null) {
                accountUserIdsLoc = regionUserIdsLoc.get(regionId);
            }

            // 过滤出 locationType 的运维人员
            Set<Integer> accountUserIdsLocFinal = accountUserIdsLoc.stream()
                    .filter(accountUserIdLoc -> accountUserLocationTypeMap.contains(accountUserIdLoc + StrPool.UNDERLINE + locationType))
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(accountUserIdsLocFinal)) {
                Map<Double, Integer> minDistance = new TreeMap<>(new Comparator<Double>() {
                    public int compare(Double obj1, Double obj2) {
                        return obj1.compareTo(obj2);
                    }
                });

                Point point = new Point();
                point.setX(machineStatus.getLon());
                point.setY(machineStatus.getLat());
                for (Integer userId : accountUserIdsLocFinal) {
                    Point pointUser = new Point();
                    pointUser.setX(map.get(userId).getLon());
                    pointUser.setY(map.get(userId).getLat());
                    minDistance.put(GeoUtil.getDistance(point, pointUser), map.get(userId).getAccountUserId());
                }

                for (int i = 0; i < minDistance.size(); i++) {
                    /**判断是否超过工单阈值*/
                    Integer userId = minDistance.values().stream().findFirst().orElse(i);
                    Integer countValue = workOrderFinishingService.getUserIdWorkTypeLocationType(userId, WorkOrderConstant.workType_NC, locationType);

                    Integer moveNumber = locationType.equals(MachineLocationTypeConstant.SUPER_ZONE_MOVE)
                            ? workOrderConfig.getSuperZoneMoveNumber() // 超区挪车数量限制
                            : workOrderConfig.getOutSiteMoveNumber(); // 站外挪车数量限制

                    if (countValue == null || countValue < moveNumber) {
                        workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                regionId, WorkOrderConstant.workType_NC, WorkOrderConstant.state_LQ, locationType);
                        JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_NC, WorkOrderConstant.new_Work);
                        work = false;
                        break;
                    }
                }
            }

            if (work) {
                if (regionId != null) {
                    accountUserIds = regionUserIds.get(regionId);
                }

                // 过滤出 locationType 的运维人员
                Set<Integer> accountUserIdsFinal = accountUserIds.stream()
                        .filter(accountUserId -> accountUserLocationTypeMap.contains(accountUserId + StrPool.UNDERLINE + locationType))
                        .collect(Collectors.toSet());

                if (CollUtil.isNotEmpty(accountUserIdsFinal)) {
                    for (Integer userId : accountUserIdsFinal) {
                        /**判断是否超过工单阈值*/
                        Integer countValue = workOrderFinishingService.getUserIdWorkTypeLocationType(userId, WorkOrderConstant.workType_NC, locationType);

                        Integer moveNumber = locationType.equals(MachineLocationTypeConstant.SUPER_ZONE_MOVE)
                                ? workOrderConfig.getSuperZoneMoveNumber() // 超区挪车数量限制
                                : workOrderConfig.getOutSiteMoveNumber(); // 站外挪车数量限制

                        if (countValue == null || countValue < moveNumber) {
                            workOrder(userId, workOrderConfig, dataService.getMachine(machineStatus.getMachineId()),
                                    regionId, WorkOrderConstant.workType_NC, WorkOrderConstant.state_LQ, locationType);
                            JPush(userId, WorkOrderConstant.buildType_V, WorkOrderConstant.workType_NC, alert);
                            break;
                        }
                    }
                }
            }

        }

    }

    @Override
    @Transactional(value = "coreTransactionManager")
    public void delWorkOrder(String workOrderId, WorkOrderFinishing workOrderFinishing) {
        workOrderService.del(workOrderId);
        workOrderFinishingService.del(workOrderId);
    }
}
